﻿using System;

namespace Samurai.Workflow
{
    public abstract class WorkflowStepBase<T> : IWorkflowStep<T> where T : class, IWorkflowContext 
    {
        private bool _isCritical = true;

        #region Implementation of IWorkflowStep<T>

        /// <summary>
        /// Occurs when the workflow step is completed.
        /// </summary>
        public event EventHandler<WorkflowStepCompletedEventArgs<T>> Completed;

        /// <summary>
        /// Occurs when the workflow step has failed execution.
        /// </summary>
        public event EventHandler<WorkflowStepCompletedEventArgs<T>> Failed;

        /// <summary>
        /// Gets or sets the context that is shared among all steps in the workflow.
        /// </summary>
        /// <value>The context.</value>
        public T Context { get; set; }

        /// <summary>
        /// Gets or sets the thread on which to execute this step.
        /// </summary>
        /// <value>The thread.</value>
        public ThreadType Thread { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to halt workflow on the failure of this step.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [halt workflow on failure]; otherwise, <c>false</c>.
        /// </value>
        public bool IsCritical
        {
            get { return _isCritical; }
            set { _isCritical = value; }
        }

        /// <summary>
        /// Gets or sets the workflow in which this step is to execute.
        /// </summary>
        /// <value>The workflow.</value>
        public IWorkflow<T> Workflow { get; set; }

        /// <summary>
        /// Gets a value indicating whether this instance has completed.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance has completed; otherwise, <c>false</c>.
        /// </value>
        public bool HasCompleted { get; protected set; }

        /// <summary>
        /// Executes the step.
        /// </summary>
        public abstract void ExecuteStep();

        #endregion

        #region Protected Members

        /// <summary>
        /// Notifies listeners that this step has completed.
        /// </summary>
        public void NotifyStepCompleted()
        {
            if(Completed != null)
                Completed(this, new WorkflowStepCompletedEventArgs<T> { Context = Context });

            HasCompleted = true;
        }

        /// <summary>
        /// Notifies listeners that this step has failed.
        /// </summary>
        public void NotifyStepFailed(Exception exception)
        {
            if(Failed != null)
                Failed(this, new WorkflowStepCompletedEventArgs<T> 
                {
                    Context = Context,
                    Exception = exception,
                    FailedWorkflowStep = this
                });
        }

        #endregion
    }
}
